﻿<!DOCTYPE HTML>
<html lang="zh">
<head>
<title>线程 - 行为 &amp; 优先级 | AutoHotkey v2</title>
<meta name="description" content="The &quot;current thread&quot; is defined as the flow of execution invoked by the most recent event; examples include hotkeys, SetTimer subroutines, custom menu items, and GUI events." />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link href="../static/theme.css" rel="stylesheet" type="text/css" />
<script src="../static/content.js" type="text/javascript"></script>
<script type="text/javascript">$(function(){0<=window.navigator.userAgent.toLowerCase().indexOf("ucbrowser")&&CaoNiMaDeUc()})</script>
</head>

<body>
<h1>线程</h1>

<p><em>当前线程</em> 的定义为最近事件调用的执行流; 例如包括<a href="../Hotkeys.htm">热键</a>, <a href="../commands/SetTimer.htm">计时器子程序</a>, <a href="../objects/Menu.htm">自定义菜单项</a>和 <a href="../objects/Gui.htm#Events">GUI 事件</a>. <em>当前线程</em> 可以在其自身子程序或该子程序调用的其他子程序中执行函数.</p>
<p>尽管 AutoHotkey 实际上并不支持多线程, 但它模拟了多线程的某些特性: 如果启动了第二个线程 -- 例如在前一个线程仍在执行时按下另一个热键 -- 那么 <em>当前线程</em> 会被中断(暂时停止) 以允许新线程变为 <em>当前线程</em>. 如果在第二个线程还在运行时又启动了第三个线程, 那么第二个和第一个线程都会进入休眠状态, 依此类推.</p>
<p>当 <em>当前线程</em> 结束时, 将恢复执行最近中断的线程, 依此类推, 直到所有线程最终结束. 当线程被恢复时, 它的设置例如 <a href="../commands/SendMode.htm">SendMode</a> 和 <a href="../commands/SetKeyDelay.htm">SetKeyDelay</a> 会自动恢复到中断前的状态; 换句话说, 中断不会给线程带来副作用(<a href="../commands/WinActivate.htm">活动窗口</a>可能发生的更改除外).</p>
<p class="note"><strong>注意</strong>: <a href="../commands/KeyHistory.htm">KeyHistory</a> 函数/菜单项会显示处于中断状态的线程数量, 而 <a href="../commands/ListHotkeys.htm">ListHotkeys</a> 函数/菜单项则显示拥有线程的热键.</p>
<p>一个脚本可以有多个同时发生的 <a href="../commands/MsgBox.htm">MsgBox</a>, <a href="../commands/InputBox.htm">InputBox</a>, <a href="../commands/FileSelect.htm">FileSelect</a> 和 <a href="../commands/DirSelect.htm">DirSelect</a> 对话框. 这是在前一个线程已经显示对话框时, 通过启动一个新的线程(通过<a href="../Hotkeys.htm">热键</a>, <a href="../commands/SetTimer.htm">计时器子程序</a>, <a href="../objects/Menu.htm">自定义菜单项</a>, 等.) 来实现的.</p>
<p>默认情况下, 如果给定的<a href="../Hotkeys.htm">热键</a>或<a href="../Hotstrings.htm">热字串</a>子程序已经在运行, 则不能再次启动. 请使用 <a href="../commands/_MaxThreadsPerHotkey.htm">#MaxThreadsPerHotkey</a> 来改变此特性.</p>
<p><strong>相关:</strong> <a href="../commands/Thread.htm">Thread</a> 函数用于设置线程的优先级或中断性.</p>

<h2 id="Priority">线程优先级</h2>
<p>任何优先级低于 <em>当前线程</em>  的线程(<a href="../Hotkeys.htm">热键</a>, <a href="../commands/SetTimer.htm">计时子程序</a>, <a href="../objects/Menu.htm">自定义菜单项</a>, 等.), 不能中断当前线程. 在这种时候, 如计时器不会运行, 任何用户创建线程(如, 通过按下<a href="../Hotkeys.htm">热键</a>或 <a href="../commands/GuiControls.htm#Button">GUI 按钮</a>) 的尝试都不会产生任何效果, 也不会被缓存起来. 由于这个原因, 通常在设计时最好让高优先级的线程快速结束, 或使用 <a href="../commands/Critical.htm">Critical</a> 而不将它们设置成高优先级.</p>
<p>默认的优先级为 0. 所有线程使用默认的优先级, 不过可以使用下列的其中一种方法来改变:<br>
  1) 通过 <a href="../commands/SetTimer.htm">SetTimer</a> 给计时子程序指定优先级.<br>
  2) 通过 <a href="../commands/Hotkey.htm">Hotkey</a> 函数给热键指定优先级.<br>
  3) 在定义<a href="../Hotstrings.htm">热字串</a>时指定优先级, 或通过 <a href="../commands/_Hotstring.htm">#Hotstring</a> 指令给热字串指定优先级.<br>
  4) 通过 <a href="../objects/Menu.htm#Add">Menu.Add</a> 方法给自定义菜单项指定优先级.<br>
  5) 通过 <a href="../commands/Thread.htm">Thread</a> 函数给 <em>当前线程</em> 设置自己的优先级.</p>
<p>不论 <em>当前线程</em> 的优先级如何, <a href="../commands/OnExit.htm">OnExit</a> 子程序(如果有) 被调用时总是会运行.</p>

<h2 id="Interrupt">线程可中断性</h2>
<p>对于大多数类型的事件, 只有在当前线程 <em>可中断</em> 的情况下, 才允许启动新的线程. 一个线程可以因为一些原因而 <em>不可中断</em>, 包括:</p>
<ul>
  <li>线程已被标记为 <em>critical</em>. <a href="../commands/Critical.htm">Critical</a> 可能已经被线程本身或被<a href="../Scripts.htm#auto">自动执行线程</a>调用.</li>
  <li>线程运行时间不够长, 无法满足线程中断设置的成为可中断的条件, 如 <a href="../commands/Thread.htm#Interrupt">Thread "Interrupt"</a> 设置的.</li>
  <li>脚本的一个菜单正在显示(如托盘图标菜单或菜单栏).</li>
  <li><a href="../commands/Send.htm">Send</a>(最常见的是由于 <a href="../commands/SetKeyDelay.htm">SetKeyDelay</a>), <a href="../commands/WinActivate.htm">WinActivate</a> 或 <a href="A_Clipboard.htm">Clipboard</a> 操作正在执行延迟.</li>
  <li><a href="../commands/OnExit.htm">OnExit</a> 子程序正在执行.</li>
  <li>由于达到了 <a href="../commands/_MaxHotkeysPerInterval.htm">#MaxHotkeysPerInterval</a> 的限制, 或者由于激活键盘或鼠标钩子的问题(非常罕见), 正在显示一个警告对话框.</li>
</ul>
<h3 id="Behave">不可中断线程的特性</h3>
<p>与高优先级线程不同, 线程不可中断时产生的事件不会被丢弃. 例如, 在当前线程不可中断时用户按下了<a href="../Hotkeys.htm">热键</a>热键就会被无限期地缓冲, 直到当前线程结束或变得可中断时, 热键才作为新的线程启动.</p>
<p>在紧急情况下, 任何线程都可能被中断. 紧急情况包括: 1) <a href="../commands/OnExit.htm">OnExit</a> 回调; 2) 任何监视消息号小于 0x312(或被这些消息触发的<a href="../commands/CallbackCreate.htm">回调</a>) 的 <a href="../commands/OnMessage.htm">OnMessage</a> 函数; 和 3) 紧急线程自身间接触发的任何<a href="../commands/CallbackCreate.htm">回调</a>(例如, 通过 <a href="../commands/PostMessage.htm">SendMessage</a> 或 <a href="../commands/DllCall.htm">DllCall</a>). 要避免被这些事件中断, 可以临时禁用这些函数.</p>
<p>当显示 <a href="../commands/MsgBox.htm">MsgBox</a> 或其他对话框时, <a href="../commands/Critical.htm">critical</a> 会变得可中断. 但与 <a href="../commands/Thread.htm">Thread Interrupt</a> 不同的是, 在用户解除对话框后, 线程又变成了 critical(因此不可中断).</p>

</body>
</html>